/**
 * @file
 * @brief Contains the TPZEqnArray class which implements an equation array.
 * @author Gustavo Longhin
 * @since 20/06/2000
 */

#ifndef TPZEQNARRAY_H
#define TPZEQNARRAY_H

#include "pzmatrix.h"
#include "pzstack.h"
#include "pzfmatrix.h"
#include "pzreal.h"
#include "pzmanvector.h"
#include "pzvec.h"

#include <stdlib.h>

#ifdef BORLAND
#include <stdio.h>
#endif

/**
 * @brief It is an equation array, generally in its decomposed form. \ref frontal "Frontal"
 * @ingroup frontal
 * @author Gustavo Longhin
 */
/** 
 * Would be saved and read from disk. \n
 * It contains a forward and a backward method. \n
 * It is sparce, symmetric or not.
 */

template<class TVar>
class TPZEqnArray {     
	
	/** @brief It defines two diferent types of storage Symmetric and NonSymmetric an also an undefined status */
	enum MSymmetric {  EIsUndefined, EIsSymmetric, EIsNonSymmetric };
	
public:
    /** @brief Static main function for testing */
	static void main();
	
    /** @brief Sets EqnArray to a non symmetric form */
    void SetNonSymmetric();
	
    /** @brief Sets fSymmetric to the symmetric value */
    void SetSymmetric();
	
    /** @brief Gets the symetry situation of EqnArray */
    int IsSymmetric();
	
    /** @brief Simple constructor */
    TPZEqnArray();
    /** @brief Simple desctructor */
    ~TPZEqnArray();
    /** 
	 * @brief Forward substitution on equations stored in EqnArray
	 * @param F Matrix to execute a Forward substitution on 
	 * @param dec Type of decomposition, depends on what method was used in its decomposition
	 */
    void EqnForward(TPZFMatrix<TVar> & F, DecomposeType dec);
    /** 
	 * @brief Backward substitution on equations stored in EqnArray 
	 * @param U Matrix to execute a Forward substitution
	 * @param dec Type of decomposition, depends on what method was used in its decomposition
	 */
    void EqnBackward(TPZFMatrix<TVar> & U, DecomposeType dec);
	
    /** @brief Resets data structure */
    void Reset();
    /** 
	 * @brief It starts an equation storage 
	 * @param eq Indicates what equation is beeing added to the stack
	 */
    void BeginEquation(int eq);
    /**
	 * @brief Add a term to the current equation 
	 * @param col The collumn position of val
	 * @param val The value beeing added itself.
	 */
    void AddTerm(int col, TVar val)
	{
		fIndex.Push(col);
		fEqValues.Push(val);
		fLastTerm++;
	} 
    /** @brief Ends the current equation */
    void EndEquation();
	
    /** @brief Reads from disk */
    void Read(char * inputfile);
	
    /** @brief Writes on disk */
    void Write(char * outputfile);
	
    /** @brief It prints all terms stored in TPZEqnArray */
    void Print(const char * name, std::ostream & out);
	
    /** @brief Writes to a file in binary mode.
	 */
	/**
     * Used by FileEqnStorage \n
     * Receives FILE and position to execute 'C' fwrite function 
     */
    void Write(FILE * outputfile);
	
	/**
     * @brief Reads from binary file generated by 'WriteBinary'
     * @note Also receives position and FILE for 'C' fread() function execution
     */
    void Read(FILE * inputfile);
	
private:
	
    /** @brief Indicates the symetry or not of the equationarray */
	MSymmetric fSymmetric;
	
	
    /** @brief Number of equations */
    int fNumEq;
	
    /** @brief Equation start point index */
    TPZStack < int , 100 > fEqStart;
    TPZStack < int , 100 > fEqNumber;
	
    /** @brief Equations coefficients values */
    TPZStack < TVar, 1000 > fEqValues;
	
    /** @brief Line/Column number associated to each fEqValues values. */
    TPZStack < int , 1000 > fIndex;
	
    /** @brief Indicates the last used position in fEqValues */
    int fLastTerm;
};

#endif //TPZEQNARRAY_H
